﻿using System;
using System.Collections.Generic;
using System.IO;
using WMPLib;

namespace ScottLane.MediaFeeder.ObjectModel
{
    /// <summary>
    /// Represents an album in the Media Player library.
    /// </summary>
    public class Album
    {
        #region Properties

        private string _albumID;

        /// <summary>
        /// Get the album identifier.
        /// </summary>
        public string AlbumID
        {
            get { return _albumID; }
        }

        private string _title;

        /// <summary>
        /// Gets the album title.
        /// </summary>
        public string Title
        {
            get { return _title; }
        }

        private string _artist;

        /// <summary>
        /// Gets the album artist.
        /// </summary>
        public string Artist
        {
            get { return _artist; }
        }

        /// <summary>
        /// Gets the album genres.
        /// </summary>
        public List<string> Genres
        {
            get
            {
                List<string> genres = new List<string>();

                foreach (Song song in _songs)
                {
                    if (song.Genre != null && !genres.Contains(song.Genre))
                    {
                        genres.Add(song.Genre);
                    }
                }

                return genres;
            }
        }

        /// <summary>
        /// Gets the total song duration.
        /// </summary>
        public TimeSpan Duration
        {
            get
            {
                TimeSpan duration = TimeSpan.Zero;

                foreach (Song song in _songs)
                {
                    duration += song.Duration;
                }

                return duration;
            }
        }

        private string _imageFileName;

        /// <summary>
        /// Gets the album image file name.
        /// </summary>
        public string ImageFileName
        {
            get { return _imageFileName; }
        }

        private List<Song> _songs = new List<Song>();

        /// <summary>
        /// Gets the album songs.
        /// </summary>
        public List<Song> Songs
        {
            get { return _songs; }
        }

        #endregion

        /// <summary>
        /// Initializes a new instance of the Album class.
        /// </summary>
        private Album()
        {
        }

        /// <summary>
        /// Initializes a new instance of the Album class with the specified identifier.
        /// </summary>
        /// <param name="albumID">The album identifier.</param>
        public Album(string albumID)
        {
            IWMPMediaCollection2 library = (IWMPMediaCollection2)MediaPlayer.Instance.mediaCollection;
            IWMPQuery query = library.createQuery();
            query.addCondition(MediaItemAttibute.AlbumID, QueryOperator.Equals, albumID);
            IWMPPlaylist playlist = library.getPlaylistByQuery(query, MediaType.Audio, MediaItemAttibute.TrackNumber, true);

            if (playlist.count == 0)
            {
                throw new ArgumentException("The specified album does not exist.", "albumID");
            }

            ParseFromPlaylist(playlist, 0);
        }

        /// <summary>
        /// Parses the album details from a Media Player playlist.
        /// </summary>
        /// <param name="playlist">The playlist.</param>
        /// <param name="startIndex">The playlist index to start at.</param>
        /// <returns>The index of the position after the latest playlist item parsed.</returns>
        private int ParseFromPlaylist(IWMPPlaylist playlist, int startIndex)
        {
            string lastAlbumID = null;

            for (int index = startIndex; index < playlist.count; index++)
            {
                IWMPMedia item = playlist.get_Item(index);
                string albumID = item.getItemInfo(MediaItemAttibute.AlbumID);

                if (albumID == string.Empty || (lastAlbumID != null && lastAlbumID != albumID))
                {
                    return index + 1;
                }
                if (lastAlbumID == null)
                {
                    _albumID = albumID;

                    if (item.getItemInfo(MediaItemAttibute.AlbumTitle) != string.Empty)
                    {
                        _title = item.getItemInfo(MediaItemAttibute.AlbumTitle);
                    }
                    if (item.getItemInfo(MediaItemAttibute.AlbumArtist) != string.Empty)
                    {
                        _artist = item.getItemInfo(MediaItemAttibute.AlbumArtist);
                    }
                    if (item.sourceURL != string.Empty)
                    {
                        FileInfo imageFile = new FileInfo(Path.Combine(Path.GetDirectoryName(item.sourceURL), "folder.jpg"));

                        if (imageFile.Exists)
                        {
                            _imageFileName = imageFile.FullName;
                        }
                    }
                }

                Song song = new Song(item);
                _songs.Add(song);
                lastAlbumID = albumID;
            }

            return playlist.count;
        }

        /// <summary>
        /// Plays the album in Media Center.
        /// </summary>
        public void Play()
        {

        }

        /// <summary>
        /// Checks whether an album with the specified identifier exists in the Media Player library.
        /// </summary>
        /// <param name="albumID">The album identifier.</param>
        /// <returns>True if the album exists, false otherwise.</returns>
        public static bool Exists(string albumID)
        {
            IWMPMediaCollection library = MediaPlayer.Instance.mediaCollection;
            IWMPPlaylist playlist = library.getByAttribute(MediaItemAttibute.AlbumID, albumID);
            return playlist.count > 0;
        }

        /// <summary>
        /// Searches for albums containing the specified title or artist.
        /// </summary>
        /// <param name="title">The album title.</param>
        /// <param name="artist">The album artist.</param>
        /// <param name="startIndex">The index of the first song to include in the results.</param>
        /// <param name="maxResults">The maximum number of songs to return.</param>
        /// <param name="exactMatch">If true, will match the specified title or artist exactly.</param>
        /// <returns>The albums found by the search.</returns>
        public static List<Album> Search(string title, string artist, int startIndex, int maxResults, bool exactMatch)
        {
            IWMPMediaCollection2 library = (IWMPMediaCollection2)MediaPlayer.Instance.mediaCollection;
            IWMPQuery query = library.createQuery();
            query.addCondition(MediaItemAttibute.AlbumID, QueryOperator.NotEquals, string.Empty);
            string queryOperator = QueryOperator.Equals;

            if (!exactMatch)
            {
                queryOperator = QueryOperator.Contains;
            }
            if (title != null)
            {
                query.addCondition(MediaItemAttibute.AlbumTitle, queryOperator, title);
            }
            if (artist != null)
            {
                query.addCondition(MediaItemAttibute.AlbumArtist, queryOperator, artist);
            }

            IWMPPlaylist playlist = library.getPlaylistByQuery(query, MediaType.Audio, MediaItemAttibute.AlbumTitle, true);
            List<Album> albums = new List<Album>();
            int index = 0;

            while (index < playlist.count)
            {
                Album album = new Album();
                index = album.ParseFromPlaylist(playlist, index);

                if (album.AlbumID != null)
                {
                    albums.Add(album);
                }
            }

            int finishIndex = albums.Count - 1;

            if (maxResults > 0)
            {
                finishIndex = startIndex + maxResults;

                if (finishIndex > albums.Count - 1)
                {
                    finishIndex = albums.Count - 1;
                }
            }
            if (startIndex != 0 && startIndex < albums.Count)
            {
                albums.RemoveRange(0, startIndex);
            }
            if (maxResults != 0 && albums.Count > maxResults)
            {
                albums.RemoveRange(maxResults, albums.Count - maxResults);
            }

            return albums;
        }
    }
}
